<template>
  <el-form ref="form" :model="form" class="form-box"
           :label-width="labelWidth"
           :inline="inline"
           :size="formSize"
           :rules="formRules"
           v-loading="loading"
           v-bind="$attrs"
           @submit.native.prevent >
    <el-row>
      <el-col v-for="(column, index) in columns"
              :key="index"
              :class="column.name+'Clz'"
              :block="column.block"
              :span="column.size || size || 8.5"
              :offset="column.offset || 0"
              :push="column.push || 0"
              :pull="column.pull || 0">
        <slot v-if="column.template" :name="column.template" :column="column" :row="form" />
        <!-- component -->
        <component
          v-else
          :rules="formRules"
          :column="column"
          :data="form"
          :is="`CM${ column.type || 'label' }`"
        />
      </el-col>
    </el-row>
  </el-form>
</template>

<script>
  import Valid from "./validate";

  const path = require('path')
  const files = require.context('./module', false, /\.vue$/)
  const modules = {}
  files.keys().forEach(key => {
    const name = path.basename(key, '.vue') // 提取出用 ‘/' 隔开的path的最后一部分,path.basename(p, [ext])。 p要处理的path,ext要过滤的字符
    modules['CM'+name] = files(key).default || files(key)
  })

  const props = {
    data:Object,
    rules:Object,
    formSize:String,
    span: {
      type: [Number],
      default: 8
    },
    columns:{
      type: [Array,Object],
      default: []
    },
    size:{
      default: 8
    },
    labelWidth:{
      type: String,
      default: '8.5vw'
    },
    inline:{
      type: [Boolean],
      default: false
    },
    autoEvent:{
      type: [Boolean],
      default: false
    },
    loading:{
      type: [Boolean],
      default: false
    },
  }

  export default {
    name: "Form",
    components:modules,
    props: props,
    dicts:[],
    data() {
      let form = this.data || {};
      let rules = Valid.formatRules(this.rules);
      this.columns.map((v)=>{
        if(v.name){
          _.extend(v,{
            prop:v.prop||v.name,
            placeholder:v.placeholder||`请输入${v.text}`,
            value: v.value || (v.type === 'checkbox' ? [] : v.value ),
            rules: Boolean(rules[v.name])
          })
          form[v.name] = v.value;
        }
      })
      //
      return {
        form:form,
        formRules:rules,
        map:{},
      }
    },
    created(){
      window.LOG || (window.LOG = ()=>{});
      window.form = this;
    },
    methods:{
      getData(isNew){
        return _.extend(isNew ? {} : this.map,this.form);
      },
      setColumn(map){
        this.columns.map((v)=>{
          let item = map[v.name];
          if(_.isNil(item)){
            //
          }else if(typeof item === 'object'){
            Object.assign(v,_.pick(item,['hide','block','span','offset','push','pull','template']))
            v.$this.setOpt(item)
          }
        })
        this.$forceUpdate();
        return this;
      },
      setData(map){// {name:{options}}
        if(!map){return this;}
        //
        Object.assign(this.map,map);// 直接合并一起
        this.columns.map((v)=>{
          let item = map[v.name];
          let itemType = Object.prototype.toString.call(item);
          if(itemType == '[object Number]'){
            item = item+'';
          }
          if(!v.name || !v.$this?.setValue || ['[object Undefined]','[object Null]'].indexOf(itemType)>-1){
            return;
          }
          //
          let actionOpt = v.$this.setOpt;
          let actionValue = v.$this.setValue;
          if(itemType == '[object Object]'){
            actionOpt(item);
            return;
          }
          // 触发change事件
          if(this.autoEvent && !v.hide && item != this.form[v.name]){
            let actionEvent = _.debounce(v.$this.setValueMap || (()=>{}),100);
            actionValue(item);
            actionEvent(item);
          }else{
            actionValue(item);
          }
        })
        return this;
      },
      setRules(map){
        this.$refs.form.clearValidate();
        Object.assign(this.$refs.form.rules,Valid.formatRules(map));
        return this;
      },
      resetForm(){
        this.columns.map((v)=>{
          if(['file','select','upload','buttons'].indexOf(v.type)>-1){
            v.$this?.setValue(v.value);
          }
        })
        this.$refs.form.resetFields();
        return this;
      },
      validate(){
        return new Promise((res,rej)=>{
          this.$refs.form.validate((valid, valData) => {
            if (valid) {
              res(_.extend(this.map,this.form));
            }else{// 提示
              console.log(valid,valData)
              for(let key in valData){
                //console.warn((valData[key][0]||{}).message);
                break;
              }
            }
          });
        })
      },
      clearValidate(){
        this.$nextTick(()=>{
          this.$refs.form.clearValidate();
        })
        return this;
      }
    }
  }
</script>


<style lang="scss">
  .form-box{
    .el-col[block="block"]{
      width:100%;
      display:block;
    }

    .el-form-item.el-form-item--default{
      height: 42px;
    }

    .el-form-item.el-form-item--medium{
      height: 38px;
    }

    .el-form-item.el-form-item--small{
      height:32px;
    }

    .el-form-item.el-form-item--mini{
      height:29px;
    }

    // 自适应高度
    .el-form-item.autoheight{
      height:auto;
    }

    // 自适应label
    .el-form-item.autolabel{
      .el-form-item__label{
        width: auto !important;
      }
      .el-form-item__content{
        margin-left:0 !important;
      }
    }

    // flex
    .el-form-item.flex{
      width: 100%;
      display: flex;
      padding-right:8px;

      .el-form-item__content{
        flex:1;
        flex-shrink: 1;
        margin-left:0 !important;
      }
    }

    // 禁用
    &.disabled{// form自带diabled不能单个启用
      .el-checkbox-group,.el-radio-group,.el-input,textarea{
        pointer-events: none; /* 禁用点击、选取等操作 */
        filter: contrast(0.93);
      }

      .el-checkbox__input.is-checked,.el-radio__input.is-checked{
        filter: opacity(0.5);
      }

      &:not(.all) .el-form-item.able{
        .el-checkbox-group,.el-radio-group,.el-input,textarea{
          pointer-events: all;
          filter: none;
        }

        .el-checkbox__input.is-checked,.el-radio__input.is-checked{
          filter: none;
        }
      }
    }

    // 文件上传：失败进度动画闪动
    .el-upload-list__item {
      transition: none !important;
    }
    .el-upload-list__item.is-ready {
      display: none;
    }
    .upload-img{
      &.is-disabled{
        .el-upload--picture-card{
          display:none;
        }

        .el-upload-list__item-delete{
          display:none;
        }
      }
    }

    .el-input__suffix-inner{
      i{
        font-style: normal;
      }
    }
  }

  // inline （去除el-row布局）
  .form-box.form-inline{
    .el-col:not([block="block"]){
      width:inherit !important;
    }

    .el-form-item__label{
      width:inherit !important;
    }

    .el-form-item__content{
      padding-right: 8px;
      margin-left:0 !important;
      display: inline-block;
    }
  }

  // 表头搜索栏 - 去掉错误提示的间距
  .form-box.form-search{
    .el-form-item{
      margin-bottom:12px;
      margin-right: 8px;
      display: flex;
    }

    .el-form-item__content{
      min-width: 182px;
      margin-left:0 !important;

      .el-date-editor--date{
        width:180px !important;
      }

      .el-date-editor--daterange{
        width:240px !important;
      }
    }

    .el-col{
      width:auto !important;
    }

    &.autolabel{
      .el-form-item{
        margin-right:.5rem;
        display: flex;
        >label{
          width: inherit !important;
          flex-shrink: 0;
        }
        >div{
          margin-left:0 !important;
          flex:1;
          flex-grow: 1;
        }
      }
    }

    .el-select{
      .el-input__inner{
        width:182px;
      }
    }
  }

  // 文本展示: show-table
  .form-box.show-table{
    .el-col{
      border:.5px solid #c4d0da;
      &.undefinedClz{
        border-color:rgba(0,0,0,0);
      }
    }

    label{
      height: 100%;
      background:#dfe6ec;
    }

    .el-form-item{
      padding-right:0px;
      margin-bottom:0;

      &.autoheight{
        flex:inherit;
        label{
          height:100%;
          position: absolute;
        }

        .el-form-item__content{
          white-space: normal;
          line-height: inherit;
        }
      }

      &:not(.autoheight){
        overflow: hidden;
      }
    }

    .el-form-item__content{
      //padding-left:3px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;

      >.txt{
        padding-left:15px;
        padding-right:15px;
      }
    }
  }

  /* 特殊定义 */
  .form-box{
    .el-col.brClz{
      min-width: 100%;
      height: 0;
    }
  }

  // 响应式布局
  @media screen and (max-width: 1100px) {
    .form-box{
      .el-col-6{
        width: 50%;
      }

      .el-col-8{
        width: 50%;
      }
    }
  }

</style>
